'''
* This is the projet for Brtc LlmOps Platform
* @Author Leon-liao <liaosiliang@alltman.com>
* @Description //TODO 
* @File: account_service.py
* @Time: 2025/10/10
* @All Rights Reserve By Brtc
'''
import base64
import secrets
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Any
from uuid import UUID

from flask import request
from injector import inject
from internal.model import Account, AccountOAuth
from internal.exception.exception import FailException
from pkg.password.password import hash_password, compare_password
from pkg.sqlachemy.sqlalchemy import SQLAlchemy
from .jwt_service import JwtService
from .base_service import BaseService



@inject
@dataclass
class AccountService(BaseService):
    """账号授权服务"""
    db:SQLAlchemy
    jwt_service:JwtService

    def get_account(self, account_id:UUID)->Account:
        """根据id 获取指定账号的信息"""
        return self.get(Account, account_id)


    def get_account_oauth_by_provider_name_and_openid(self, provider_name:str, openid:str)->AccountOAuth:
        """根据传递第三方登录提供商， 获取第三方认证记录"""
        return self.db.session.query(AccountOAuth).filter(
                        AccountOAuth.provider==provider_name,
                        AccountOAuth.openid==openid
                ).one_or_none()


    def get_account_by_email(self, email:str)->Account:
        """根据邮箱信息获取账号信息"""
        return self.db.session.query(Account).filter(
                    Account.email==email,
                ).one_or_none()


    def create_account(self, **kwargs)->Account:
        """根据传递的信息创建一个新的账号"""
        return self.create(Account, **kwargs)


    def update_password(self,  password:str, account:Account)->Account:
        """根据传递的信息更新账号密码"""
        #1、生成密码的随机盐值
        salt = secrets.token_bytes(16)
        base64_salt = base64.b64encode(salt).decode()
        #2、利用盐值和password 进行加密
        password_hashed = hash_password(password, salt)
        base64_password_hashed = base64.b64encode(password_hashed).decode()
        #3、更新账号信息
        self.update_account(account, password=base64_password_hashed, password_salt=base64_salt)
        return account


    def update_account(self, account:Account, **kwargs)->Account:
        """更新账号信息"""
        self.update(account, **kwargs)
        return account


    def password_login(self, email:str, password:str)->dict[str, Any]:
        """根据传递的密码  +  邮箱 登录特定的账号"""
        #1、根据传递的邮箱查询账号是否存在
        account = self.get_account_by_email(email)
        if not account:
            raise FailException("账号不存在，或者密码错误， 请核实后重试！")
        #2、校验密码是否正确
        if not  account.is_password_set or not  compare_password(
            password,
            account.password,
            account.password_salt
        ):
            raise FailException("密码&账号校验错误， 请核实后重试！")

        #3、生成凭证信息
        expire_at = int((datetime.now() + timedelta(days=30)).timestamp())
        payload = {
            "sub":str(account.id),
            "exp":expire_at,
            "iss":"llmops_ai_plat"
        }
        access_token = self.jwt_service.generate_token(payload)

        # 4、更新账号信息
        self.update(
            account,
            last_login_at=datetime.now(),
            last_login_ip= request.remote_addr,
        )

        return {
            "expire_at":expire_at,
            "access_token":access_token,
        }

